"""
数据处理模块
负责数据的清洗、格式转换、预处理和异常值处理
"""

import pandas as pd
import numpy as np


class DataProcessor:
    """数据处理器"""
    
    def __init__(self):
        """初始化数据处理器"""
        pass
    
    def convert_date_format(self, date_str):
        """
        转换日期格式：DD-MM-YYYY -> YYYY-MM-DD
        
        Args:
            date_str: 原始日期字符串
        
        Returns:
            str: 转换后的日期字符串
        """
        try:
            parts = date_str.split('-')
            if len(parts) == 3:
                # 处理年份：如果是两位数则加前缀20，如果已经是四位数则保持不变
                year = parts[2]
                if len(year) == 2:
                    year = f"20{year}"
                elif len(year) != 4:
                    # 如果年份既不是2位也不是4位，直接返回原字符串
                    return date_str
                
                return f"{year}-{parts[1].zfill(2)}-{parts[0].zfill(2)}"
            return date_str
        except Exception:
            return date_str
    
    def remove_outliers(self, df, exclude_columns=None):
        """
        移除异常值（使用1%-99%分位数截断）
        
        Args:
            df: 输入DataFrame
            exclude_columns: 不处理的列名列表
        
        Returns:
            DataFrame: 处理后的DataFrame
        """
        if exclude_columns is None:
            exclude_columns = ['Room_Occupancy_Count']
        
        df_processed = df.copy()
        
        # 对数值列进行异常值处理
        numeric_columns = df_processed.select_dtypes(include=['float64', 'int64']).columns
        
        for col in numeric_columns:
            if col not in exclude_columns:
                # 计算1%和99%分位数
                q1 = df_processed[col].quantile(0.01)
                q3 = df_processed[col].quantile(0.99)
                iqr = q3 - q1
                
                # 截断异常值
                df_processed[col] = df_processed[col].clip(
                    q1 - 1.5 * iqr, 
                    q3 + 1.5 * iqr
                )
        
        return df_processed
    
    def add_time_features(self, df):
        """
        添加时间特征
        
        Args:
            df: 输入DataFrame
        
        Returns:
            DataFrame: 添加时间特征后的DataFrame
        """
        df_processed = df.copy()
        
        try:
            # 组合日期和时间，使用更灵活的解析方式
            datetime_strings = df_processed['StandardDate'] + ' ' + df_processed['Time']
            
            # 首先尝试标准格式
            try:
                df_processed['DateTime'] = pd.to_datetime(
                    datetime_strings,
                    format='%Y-%m-%d %H:%M:%S'
                )
            except ValueError:
                # 如果标准格式失败，使用自动推断
                print("标准时间格式解析失败，尝试自动推断格式...")
                df_processed['DateTime'] = pd.to_datetime(
                    datetime_strings,
                    errors='coerce'  # 无法解析的设为NaT
                )
                
                # 移除无法解析的行
                invalid_rows = df_processed['DateTime'].isna().sum()
                if invalid_rows > 0:
                    print(f"发现 {invalid_rows} 行无效的时间数据，已移除")
                    df_processed = df_processed.dropna(subset=['DateTime'])
            
            # 提取时间特征
            df_processed['Hour'] = df_processed['DateTime'].dt.hour
            df_processed['DayOfWeek'] = df_processed['DateTime'].dt.dayofweek
            df_processed['IsWeekend'] = (df_processed['DayOfWeek'] >= 5).astype(int)
            
            # 添加周期性特征
            df_processed['Hour_sin'] = np.sin(2 * np.pi * df_processed['Hour'] / 24)
            df_processed['Hour_cos'] = np.cos(2 * np.pi * df_processed['Hour'] / 24)
            df_processed['DayOfWeek_sin'] = np.sin(2 * np.pi * df_processed['DayOfWeek'] / 7)
            df_processed['DayOfWeek_cos'] = np.cos(2 * np.pi * df_processed['DayOfWeek'] / 7)
            
        except Exception as e:
            print(f"添加时间特征时出错: {e}")
            # 返回原数据，但添加默认时间特征
            df_processed['Hour'] = 12  # 默认中午
            df_processed['DayOfWeek'] = 1  # 默认周二
            df_processed['IsWeekend'] = 0  # 默认工作日
            df_processed['Hour_sin'] = 0
            df_processed['Hour_cos'] = 1
            df_processed['DayOfWeek_sin'] = 0
            df_processed['DayOfWeek_cos'] = 1
        
        return df_processed
    
    def apply_date_filter(self, df, start_date=None, end_date=None):
        """
        应用日期筛选
        
        Args:
            df: 输入DataFrame
            start_date: 开始日期
            end_date: 结束日期
        
        Returns:
            DataFrame: 筛选后的DataFrame
        """
        if start_date and end_date:
            mask = (df['StandardDate'] >= start_date) & (df['StandardDate'] <= end_date)
            return df[mask].reset_index(drop=True)
        return df
    
    def downsample_data(self, df, max_points):
        """
        数据降采样
        
        Args:
            df: 输入DataFrame
            max_points: 最大数据点数量
        
        Returns:
            DataFrame: 降采样后的DataFrame
        """
        if max_points and len(df) > max_points:
            # 使用均匀间隔采样
            step = max(1, len(df) // max_points)
            return df.iloc[::step, :].reset_index(drop=True)
        return df
    
    def validate_data(self, df):
        """
        验证数据完整性
        
        Args:
            df: 输入DataFrame
        
        Returns:
            tuple: (is_valid, error_message)
        """
        try:
            # 检查必需的列
            required_columns = ['Date', 'Time', 'Room_Occupancy_Count']
            missing_columns = [col for col in required_columns if col not in df.columns]
            
            if missing_columns:
                return False, f"缺少必需的列: {missing_columns}"
            
            # 检查数据是否为空
            if df.empty:
                return False, "数据为空"
            
            # 检查关键列是否有空值
            for col in required_columns:
                if df[col].isna().any():
                    return False, f"列 {col} 包含空值"
            
            return True, "数据验证通过"
            
        except Exception as e:
            return False, f"数据验证出错: {str(e)}"
    
    def get_data_summary(self, df):
        """
        获取数据摘要信息
        
        Args:
            df: 输入DataFrame
        
        Returns:
            dict: 数据摘要信息
        """
        try:
            summary = {
                "total_records": len(df),
                "columns": list(df.columns),
                "date_range": {
                    "start": df['StandardDate'].min() if 'StandardDate' in df.columns else None,
                    "end": df['StandardDate'].max() if 'StandardDate' in df.columns else None
                },
                "occupancy_stats": {
                    "min": df['Room_Occupancy_Count'].min() if 'Room_Occupancy_Count' in df.columns else None,
                    "max": df['Room_Occupancy_Count'].max() if 'Room_Occupancy_Count' in df.columns else None,
                    "mean": df['Room_Occupancy_Count'].mean() if 'Room_Occupancy_Count' in df.columns else None
                },
                "missing_values": df.isna().sum().to_dict(),
                "data_types": df.dtypes.astype(str).to_dict()
            }
            return summary
        except Exception as e:
            return {"error": f"生成数据摘要时出错: {str(e)}"}
    
    def preprocess_raw_data(self, df):
        """
        预处理原始数据的完整流程
        
        Args:
            df: 原始DataFrame
        
        Returns:
            DataFrame: 预处理后的DataFrame
        """
        try:
            # 1. 验证数据
            is_valid, message = self.validate_data(df)
            if not is_valid:
                raise ValueError(f"数据验证失败: {message}")
            
            # 2. 转换日期格式
            df_processed = df.copy()
            df_processed['StandardDate'] = df_processed['Date'].apply(self.convert_date_format)
            
            # 3. 移除异常值
            df_processed = self.remove_outliers(df_processed)
            
            # 4. 添加时间特征
            df_processed = self.add_time_features(df_processed)
            
            print(f"数据预处理完成，处理了 {len(df_processed)} 条记录")
            return df_processed
            
        except Exception as e:
            print(f"数据预处理出错: {e}")
            raise
    
    def process_for_api(self, df, max_points=None, start_date=None, end_date=None):
        """
        为API调用处理数据
        
        Args:
            df: 输入DataFrame
            max_points: 最大数据点数量
            start_date: 开始日期
            end_date: 结束日期
        
        Returns:
            list: 处理后的数据字典列表
        """
        try:
            # 1. 应用日期筛选
            df_filtered = self.apply_date_filter(df, start_date, end_date)
            
            # 2. 应用降采样
            df_sampled = self.downsample_data(df_filtered, max_points)
            
            # 3. 转换为字典列表
            result = df_sampled.to_dict('records')
            
            return result
            
        except Exception as e:
            print(f"API数据处理出错: {e}")
            raise 